package com.voice.call.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import voice.voice.call.cache.SmsCountCache;

import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse.SmsSendDetailDTO;
import com.voice.call.common.Const;
import com.voice.call.common.Result;
import com.voice.call.common.ResultEnum;
import com.voice.call.entity.SmsLog;
import com.voice.call.entity.UserInfo;
import com.voice.call.mapper.SmsLogMapper;
import com.voice.call.service.AliSmsService;
import com.voice.call.service.NexmoService;
import com.voice.call.service.OpLogService;
import com.voice.call.service.SmsLogService;
import com.voice.call.service.SupportMccService;
import com.voice.call.service.UserInfoService;
import com.voice.call.util.entity.SupportRegister;
import com.voice.call.utils.DateUtil;
import com.voice.call.utils.JSONUtil;
import com.voice.call.utils.StringUtil;

@Service
public class SmsLogServiceImpl implements SmsLogService{
	
	private static final Logger log = LoggerFactory.getLogger(SmsLogServiceImpl.class);
	
	@Resource
	private SmsCountCache smsCountCache;
	
	@Resource
	private Properties configProperties;
	
	@Resource
	private AliSmsService aliSmsService;
	
	@Resource
	private SmsLogMapper smsLogMapper;
	
	@Resource
	private SupportMccService supportMccService;
	
	@Resource
	private NexmoService nexmoService;
	
	@Resource
	private OpLogService opLogService;
	
	@Resource
	private UserInfoService userInfoService;
	
	
	private int getSmsPhoneCount(String phone,String type) {

		Date nowDate = new Date();
		
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("phone", phone);
		params.put("type", type);
		params.put("startTime", DateUtil.getDateTimeString(nowDate, DateUtil.DATE_FMT)+" 00:00:00");
		params.put("endTime", DateUtil.getDateTimeString(nowDate, DateUtil.DATE_TIME_FMT));
		
		int total = smsLogMapper.getPhoneSendCount(params);
		
		return total;
		
	}

	@Override
	public Result sendMsg(String v,String ip, String deviceNo,String phone,String smsType){
		
		SupportRegister supportRegister=supportMccService.handlerSupportRegister(ip, "");
		//1.是否ip支持注册
		if (!supportRegister.isSupport()) {
			log.info("sms当前所在区不支持注册");
			return new Result(ResultEnum.REGISTER_MCC_ERROR);
		}

		//2.国家码支持注册区域
		if (supportMccService.getSupportLoginBindPhoneCount(phone.replaceAll("^00", "")) == 0) { 
			return new Result(ResultEnum.REGISTER_MCC_ERROR);
		}
		
		//3.判断数据库中是否已经验证过为无效号码
		if (opLogService.existsValidPhone(phone)) {
			return new Result(ResultEnum.INVALID_MOBILE_ERROR);
		}
		
		//4.手机号码未注册过
		UserInfo  userInfo=userInfoService.findByPhone(phone);
		if (userInfo == null) { 
			//4.1 手机号码未注册过，则在nexmo中验证手机号码是否有效
			StringBuilder nexmoStatusBuilder = new StringBuilder();
			if(!nexmoService.checkPhone(phone,nexmoStatusBuilder)){ 
				//写日志
				boolean isWriteLog = true;
				if(nexmoStatusBuilder.length()>0&&nexmoStatusBuilder.toString().equals("9")) {
					isWriteLog = false; //没有钱，不写日志
				}
				if (isWriteLog) {
					opLogService.phoneWriteLog(phone, v, ip);
				}
				return new Result(ResultEnum.INVALID_MOBILE_ERROR);
			}
		}else {
			//4.2.手机号码已注册过，则判断是否为已经被封的手机号码
			if (userInfo.getStatus().equals(Const.N)) {
				return new Result(ResultEnum.INVALID_MOBILE_ERROR);
			}
		}


		String smsLimit = configProperties.getProperty(Const.SMS_LIMIT);
		//2.短信发送超出限制
		Integer limit = Integer.parseInt(smsLimit);
		int sendSmsCount = getSmsPhoneCount(phone,smsType);
		if (sendSmsCount>=limit.intValue()) {
			return new Result(ResultEnum.SMS_SEND_LIMIT);
		}
		
		/***
		if(smsCountCache.get(ip)>limit || smsCountCache.get(deviceNo)>limit || smsCountCache.get(phone)>limit){
			return new Result(ResultEnum.SMS_SEND_LIMIT);
		}***/
		
		
		//随机生成4位短信验证码
		String verifyCode = StringUtil.buildRandomCode(4);
		//短信内容
		String content = "模版为:"+smsType+",验证码为:"+verifyCode;
		//短信log
		SmsLog sl = new SmsLog(ip, deviceNo, phone,smsType, verifyCode, content, Const.N, "", new Date());
		
		try {
			
			StringBuilder sBizid = new StringBuilder();
			boolean success = aliSmsService.sendAliSms(phone, verifyCode, smsType,sBizid);
			sl.setRemark("");
			if(success){
				sl.setStatus(Const.Y);
				sl.setBizid(sBizid.toString());
				smsLogMapper.insert(sl);
				smsCountCache.increase(ip);
				smsCountCache.increase(deviceNo);
				smsCountCache.increase(phone);
				return new Result();
			}
		} catch (Exception e) {
			log.error(ResultEnum.HTTP_CONNECT_ERROR.getMsg()+":{}",e);
			sl.setRemark(ResultEnum.HTTP_CONNECT_ERROR.getMsg());
			return new Result(ResultEnum.HTTP_CONNECT_ERROR);
		}
		//smsLogMapper.insert(sl);
		return new Result(ResultEnum.SMS_SEND_FAIL);
	}
	
	@Override
	public boolean smsVerify(String phone,String vcode,String smsType,StringBuilder isSending){
		
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("phone", phone);
		params.put("type", smsType);
		SmsLog ms = smsLogMapper.getTypeSMSOne(params);
		String smsValid = configProperties.getProperty(Const.SMS_VALID);
		String smsValidCount = configProperties.getProperty(Const.SMS_VERIFY_COUNT); //短信验证次数
		
		if (ms!=null && ms.getVerifyCount().intValue()>=Integer.valueOf(smsValidCount).intValue()) { //
			log.info("超过短信最大验证次数");
			return false;
		}
		
		//判断是否已回复，未回复，则查询更新数据
		if (ms!=null&&ms.getReplyStatus().equals(Const.N)) { //未回复
			SmsSendDetailDTO detail=aliSmsService.queryDetail(ms.getPhone(), ms.getBizid(), ms.getCtime());
			if (detail!=null) {
				log.info("查询结果={}",JSONUtil.objectToJson(detail));
				if (detail.getSendStatus() == 1) { //等待回执 (短信还在发送中)
					isSending.append(Const.SMS_SENDING);
					log.info("等待回执 (短信还在发送中)");
					return false;
				}
				ms.setReplyStatus(Const.Y);
				if (detail.getSendStatus() == 3) { //发送成功
					ms.setSendStatus(Const.Y);
					ms.setRemark("短信发送成功");
				}else if (detail.getSendStatus()==2){ //发送失败
					ms.setSendStatus(Const.N);
					ms.setRemark(JSONUtil.objectToJson(detail));
				}
				ms.setMtime(new Date());
				log.info("修改对象={}",JSONUtil.objectToJson(ms));
				if(smsLogMapper.update(ms)>0){
					log.info("更新短信状态成功");
				}else{
					log.error("更新短信状态失败");
				}
			}
			
		}
		
		if (ms!=null&&ms.getReplyStatus().equals(Const.Y)) { //已回复
			
			
			//更新短信验证次数
			SmsLog updateSms = new SmsLog();
			updateSms.setId(ms.getId());
			updateSms.setVerifyCount(1);
			updateSms.setMtime(new Date());
			if(smsLogMapper.update(updateSms)>0){
				log.info("更新短信验证次数成功");
			}else{
				log.error("更新短信验证次数失败");
			}
			
			if (ms.getSendStatus().equals(Const.N)) { //短信发送失败
				log.info("短信发送失败,phone={}",phone);
				return false;
			}
			
			Date nowDate = new Date();
			Date validateTime = DateUtil.addSecond(ms.getCtime(), Integer.valueOf(smsValid) * 60);
			if (vcode.equals(ms.getVerifyCode()) && validateTime.compareTo(nowDate)>=0) {
				log.error("短信验证码验证成功，phone={}",phone);
				return true;
			}
			log.info("短信验证码验证失败，phone={},code={}",phone,vcode);
			return false;
			
			
		}
		
		return false;
		
		
	}
}
